package com.middlegroup.pay.service.impl;

import com.middlegroup.common.exception.BaseException;
import com.middlegroup.common.exception.BusinessException;
import com.middlegroup.common.exception.ErrorMsg;
import com.middlegroup.common.model.TransRequest;
import com.middlegroup.common.model.TransResult;
import com.middlegroup.common.utils.CronUtils;
import com.middlegroup.common.utils.RandomUtils;
import com.middlegroup.pay.dto.RouterRequest;
import com.middlegroup.pay.dto.RouterResponse;
import com.middlegroup.pay.entity.MerchantSubjectChannelRouter;
import com.middlegroup.pay.mapper.MerchantSubjectChannelRouterMapper;
import com.middlegroup.pay.service.MerchantSubjectChannelRouterService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.ParseException;
import java.util.*;

/**
 * <p>
 * 商户主体通道路由表 服务实现类
 * </p>
 *
 * @author pc123
 * @since 2019-01-04
 */
@Service
public class MerchantSubjectChannelRouterServiceImpl extends ServiceImpl<MerchantSubjectChannelRouterMapper, MerchantSubjectChannelRouter> implements MerchantSubjectChannelRouterService {


    @Resource
    private MerchantSubjectChannelRouterMapper merchantSubjectChannelRouterMapper;

    @Override
    @Cacheable(value = "router",key = "#p0.merchantCode+#p0.bankCode+#p0.serviceType", unless = "#result eq null")
    public RouterResponse router(RouterRequest request) throws BusinessException, ParseException {
        //查出商户所拥有的主体通道
        List<RouterResponse> routerResponseList = merchantSubjectChannelRouterMapper.router(request);
        if (CollectionUtils.isEmpty(routerResponseList)) {
            //商户未配置可用的主体通道
            throw new BusinessException(ErrorMsg.NOT_CONFIG_ROUTER);
        }
        Map<String, RouterResponse> highLevel = new HashMap<>();
        Map<String, RouterResponse> middleLevel = new HashMap<>();
        Map<String, RouterResponse> lowLevel = new HashMap<>();
        //时间优先级检查
        int size = routerResponseList.size();
        for (int i = 0; i < size; i++) {
            RouterResponse routerResponse = routerResponseList.get(i);
            String cronStr = routerResponse.getInvalidTime();
            if (routerResponse.getLevel().intValue() == 1) {
                //高优先级
                highLevel.put(routerResponse.getSubjectChannelId().toString(),routerResponse);
            } else if (routerResponse.getLevel().intValue() == 2) {
                middleLevel.put(routerResponse.getSubjectChannelId().toString(),routerResponse);
            } else if (routerResponse.getLevel().intValue() == 3) {
                //低优先级
                lowLevel.put(routerResponse.getSubjectChannelId().toString(),routerResponse);
            }
            if (StringUtils.isNotBlank(cronStr)) {
                //有时间规则，则校验并做相应剔除动作
                Date now = new Date();
                if (CronUtils.isSatisfiedBy(now, cronStr)) {
                    //满足则剔除
                    routerResponseList.remove(i);
                    i--;
                }
            }
        }
        if (CollectionUtils.isEmpty(routerResponseList)) {
            throw new BusinessException("未找到合适的路由!");
        }
        RouterResponse routerResponse = null;

        //根据优先级和权重返回最终的路由渠道
        //高优先级筛选一遍，如果有则直接定返回
        routerResponse = selectByLevel(highLevel);
        if (null != routerResponse){
            return routerResponse;
        }

        //中优先级筛选一遍，如果有则直接定返回
        routerResponse = selectByLevel(middleLevel);
        if (null != routerResponse){
            return routerResponse;
        }

        //低优先级筛选一遍，如果有则直接定返回
        routerResponse = selectByLevel(lowLevel);
        if (null != routerResponse){
            return routerResponse;
        }

        throw new BusinessException("未选择到渠道，请检查配置!");
    }

    @Override
    public RouterResponse refreshRouter(RouterRequest request) throws BaseException, ParseException {
        return null;
    }


    /**从不同级别中获取最终的路由
     * @param levelMap key 是subjectChannelId，value是RouterResponse
     * @return
     */
    private  RouterResponse selectByLevel(Map<String,RouterResponse> levelMap){
        RouterResponse response = null;
        if (null != levelMap && levelMap.size() > 0){
            Set<Map.Entry<String, RouterResponse>> set = levelMap.entrySet();
            Iterator<Map.Entry<String, RouterResponse>> it = set.iterator();
            Map<String,Integer> waitSelect = new HashMap<String,Integer>();
            while (it.hasNext()) {
                // 返回的是封装了key和value对象的Map.Entry对象
                Map.Entry<String, RouterResponse> entry = it.next();
                // 获取Map.Entry对象中封装的key和value对象
                String key = entry.getKey();
                RouterResponse routerResponse = entry.getValue();
                waitSelect.put(key,routerResponse.getWeight());
            }
            String subjectChannelId = RandomUtils.chanceSelect(waitSelect);
            if (StringUtils.isNotBlank(subjectChannelId)){
                //如果高优先级选中则低的不考虑
                return levelMap.get(subjectChannelId);
            }
        }
        return response;
    }

}
